package org.example.coursemangementserver.server.service.impl.teacher;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.example.coursemangementserver.common.constant.JwtClaimsConstant;
import org.example.coursemangementserver.common.context.BaseContext;
import org.example.coursemangementserver.common.exception.common.CommonException;
import org.example.coursemangementserver.common.properties.JwtProperties;
import org.example.coursemangementserver.common.utils.Aes;
import org.example.coursemangementserver.common.utils.JwtUtil;
import org.example.coursemangementserver.pojo.dto.UserLoginDTO;
import org.example.coursemangementserver.pojo.dto.UserRegisterDTO;
import org.example.coursemangementserver.pojo.dto.Pagination;
import org.example.coursemangementserver.pojo.dto.course.*;
import org.example.coursemangementserver.pojo.dto.course.StudentCommentListQuery.GetStudentCommentListDTO;
import org.example.coursemangementserver.pojo.dto.course.TeacherCourseQuery.GetTeacherCourseListDTO;
import org.example.coursemangementserver.pojo.dto.student.TeacherGetStudentOnCourseListDTO;
import org.example.coursemangementserver.pojo.dto.teacher.RemoveStudentFromCourseDTO;
import org.example.coursemangementserver.pojo.dto.teacher.TeacherListQuery.GetTeacherListDTO;
import org.example.coursemangementserver.pojo.dto.teacher.TeacherListQuery.QueryParams;
import org.example.coursemangementserver.pojo.dto.teacher.TeacherNewInfoDTO;
import org.example.coursemangementserver.pojo.entity.*;
import org.example.coursemangementserver.pojo.vo.UserLoginVO;
import org.example.coursemangementserver.pojo.vo.course.StudentCommentList.StudentCommentListVO;
import org.example.coursemangementserver.pojo.vo.course.StudentCommentList.StudentCommentVO;
import org.example.coursemangementserver.pojo.vo.course.StudentCourseList.StudentCourseVO;
import org.example.coursemangementserver.pojo.vo.course.TeacherCourseList.TeacherCourseListVO;
import org.example.coursemangementserver.pojo.vo.course.TeacherCourseList.TeacherCourseVO;
import org.example.coursemangementserver.pojo.vo.student.TeacherGetStudentListOnCourse.StudentInfoVO;
import org.example.coursemangementserver.pojo.vo.student.TeacherGetStudentListOnCourse.StudentListVO;
import org.example.coursemangementserver.pojo.vo.teacher.TeacherAuditingInfoList.TeacherAuditingListInfoVO;
import org.example.coursemangementserver.pojo.vo.teacher.TeacherAuditingInfoVO;
import org.example.coursemangementserver.pojo.vo.teacher.TeacherInfoList.TeacherListVO;
import org.example.coursemangementserver.pojo.vo.teacher.TeacherInfoVO;
import org.example.coursemangementserver.pojo.vo.teacher.TeacherVO;
import org.example.coursemangementserver.server.mapper.*;
import org.example.coursemangementserver.server.service.interfac.teacher.TeacherService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author 12438
 */
@Service
@Slf4j
public class TeacherServiceImpl extends ServiceImpl<TeacherMapper, Teacher> implements TeacherService {
    @Autowired
    TeacherMapper  teacherMapper;
    @Autowired
    CourseMapper courseMapper;
    @Autowired
    CourseReviewMapper  courseReviewMapper;
    @Autowired
    private EnrollmentMapper enrollmentMapper;
    @Autowired
    private SelectionInformationMapper selectionInformationMapper;
    @Autowired
    private StudentMapper studentMapper;
    /**
     * 注入JWT令牌相关属性
     */
    @Autowired
    private JwtProperties jwtProperties;
    /**
     * 教师登录
     * @param userLoginDTO
     * @return
     */
    @Override
    public UserLoginVO login(UserLoginDTO userLoginDTO) {
        Teacher teacher = teacherMapper.selectByTeacherNum(userLoginDTO.getUsername());
        String password = Aes.decrypt(userLoginDTO.getPassword());
        if ( teacher!=null && password.equals(teacher.getPassword()) ){
            if (teacher.getStatus() != 1) {
                // 抛出异常提示用户被禁用
                throw new CommonException("账户被禁用或者审核中，请联系管理员");
            }
            // 登录成功，生成JWT令牌
            Map<String,Object> claims = new HashMap<>();
            claims.put(JwtClaimsConstant.USER_ID,teacher.getTeacherId());
            claims.put(JwtClaimsConstant.USERNAME,teacher.getTeacherNum());
            String jwtToken = JwtUtil.createJwt(claims,jwtProperties.getTeacherSecretKey(), jwtProperties.getExpireTime());
            return new UserLoginVO(teacher.getTeacherId(),teacher.getTeacherNum(), jwtToken,2,teacher.getName(),teacher.getAvatarUrl());
        } else {
            // 抛出异常提示密码或者用户名错误
            throw new CommonException("密码或者用户名错误，教师登录失败");
        }
    }

    /**
     * 老师提交注册申请
     * @param userRegisterDTO
     */
    @Override
    public void register(UserRegisterDTO userRegisterDTO) {
        userRegisterDTO.setPassword(Aes.decrypt(userRegisterDTO.getPassword()));
        Teacher  teacher = new Teacher();
        BeanUtils.copyProperties(userRegisterDTO,teacher);
        teacher.setTeacherNum(userRegisterDTO.getUsername());
        teacherMapper.insert(teacher);

    }

    /**
     * 获取老师待审核信息
     * @return
     */
    @Override
    public TeacherAuditingListInfoVO getTeacherAuditing(Pagination pagination) {
        Integer start = (pagination.getCurrentPage()-1) * pagination.getPageSize();
        Integer total =  teacherMapper.getTeacherAuditingCount();
        List<TeacherAuditingInfoVO> teacherAuditingListInfoVOList = teacherMapper.getTeacherAuditing(start,pagination.getPageSize());
        return new TeacherAuditingListInfoVO(total,teacherAuditingListInfoVOList);
    }

    /**
     * 获取所有老师信息
     * @param getTeacherListDTO
     * @return
     */
    @Override
    public TeacherListVO getTeacherList(GetTeacherListDTO getTeacherListDTO) {
        Pagination  pagination = getTeacherListDTO.getPagination();
        Integer start = (pagination.getCurrentPage()-1) * pagination.getPageSize();
        QueryParams  queryParams = getTeacherListDTO.getQueryParams();
        if (queryParams!=null) {
            Integer total =  teacherMapper.getTeacherTotal(queryParams.getName());
            List<TeacherVO>  teacherList = teacherMapper.getTeacherList(start,pagination.getPageSize(),queryParams.getName());
            return new TeacherListVO(total,teacherList);
        }
        Integer total =  teacherMapper.getTeacherTotal(null);
        List<TeacherVO>  teacherList = teacherMapper.getTeacherList(start,pagination.getPageSize(),null);
        return new TeacherListVO(total,teacherList);
    }

    /**
     * 处理老师获取自己所授课程信息的请求
     * @param getTeacherCourseListDTO
     * @return
     */
    @Override
    public TeacherCourseListVO getTeacherCourseList(GetTeacherCourseListDTO getTeacherCourseListDTO) {
        Pagination pagination = getTeacherCourseListDTO.getPagination();
        Integer start = (pagination.getCurrentPage()-1) * pagination.getPageSize();
        org.example.coursemangementserver.pojo.dto.course.TeacherCourseQuery.QueryParams queryParams = getTeacherCourseListDTO.getQueryParams();
        if (queryParams != null){
            Integer total = courseMapper.getTeacherCourseTotal(BaseContext.getCurrentUser().getUserId(),queryParams.getName());
            List<TeacherCourseVO> teacherCourseVOList = courseMapper.getTeacherCourseList(start,pagination.getPageSize(),BaseContext.getCurrentUser().getUserId(),queryParams.getName());
            return new TeacherCourseListVO(total,teacherCourseVOList);
        }
        Integer total = courseMapper.getTeacherCourseTotal(BaseContext.getCurrentUser().getUserId(),null);
        List<TeacherCourseVO> teacherCourseVOList = courseMapper.getTeacherCourseList(start,pagination.getPageSize(),BaseContext.getCurrentUser().getUserId(),null);
        return new TeacherCourseListVO(total,teacherCourseVOList);
    }

    /**
     * 处理老师获取自己的课程的评价信息
     * @param getStudentCommentListDTO
     * @return
     */
    @Override
    public StudentCommentListVO getStudentCommentList(GetStudentCommentListDTO getStudentCommentListDTO) {
        Pagination pagination = getStudentCommentListDTO.getPagination();
        Integer start = (pagination.getCurrentPage()-1) * pagination.getPageSize();
        org.example.coursemangementserver.pojo.dto.course.StudentCommentListQuery.QueryParams queryParams = getStudentCommentListDTO.getQueryParams();
        if (queryParams != null){
            Integer total = courseReviewMapper.getStudentCommentTotal(BaseContext.getCurrentUser().getUserId(),queryParams.getName(),queryParams.getStudentName());
            List<StudentCommentVO> studentCommentListVOList = courseReviewMapper.getStudentCommentList(start,pagination.getPageSize(),BaseContext.getCurrentUser().getUserId(),queryParams.getName(),queryParams.getStudentName());
            return new StudentCommentListVO(total,studentCommentListVOList);
        }
        Integer total = courseReviewMapper.getStudentCommentTotal(BaseContext.getCurrentUser().getUserId(),null,null);
        List<StudentCommentVO> studentCommentListVOList = courseReviewMapper.getStudentCommentList(start,pagination.getPageSize(),BaseContext.getCurrentUser().getUserId(),null,null);
        return new StudentCommentListVO(total,studentCommentListVOList);
    }

    @Override
    public StudentCommentListVO getEnrollmentCommentList(GetEnrollmentCommentDTO getEnrollmentCommentDTO) {
        Integer total = courseReviewMapper.getEnrollmentCommentTotal(getEnrollmentCommentDTO.getEnrollmentId());
        List<StudentCommentVO> studentCommentListVOList = courseReviewMapper.getEnrollmentCommentList(getEnrollmentCommentDTO.getEnrollmentId());
        return new StudentCommentListVO(total,studentCommentListVOList);
    }

    /**
     * 获取老师个人信息
     * @return
     */
    @Override
    public TeacherInfoVO getTeacherDetail() {
        Teacher teacher = teacherMapper.selectById(BaseContext.getCurrentUser().getUserId());
        TeacherInfoVO teacherInfoVO = new TeacherInfoVO();
        BeanUtils.copyProperties(teacher,teacherInfoVO);
        return teacherInfoVO;
    }

    /**
     * 教师修改自己的个人信息
     * @param teacherNewInfoDTO
     */
    @Override
    public void updateTeacherInfo(TeacherNewInfoDTO teacherNewInfoDTO) {
        Teacher teacher = teacherMapper.selectById(BaseContext.getCurrentUser().getUserId());
        teacher.setName(teacherNewInfoDTO.getName());
        teacher.setTeacherNum(teacherNewInfoDTO.getTeacherNum());
        teacher.setAvatarUrl(teacherNewInfoDTO.getAvatarUrl());
        if (teacherNewInfoDTO.getPassword()!=null){
            teacher.setPassword(Aes.decrypt(teacherNewInfoDTO.getPassword()));
        }
        teacherMapper.updateById(teacher);
    }

    /**
     * 老师结束自己的课程
     * @param endCourseDTO
     */
    @Override
    public void endCourse(EndCourseDTO endCourseDTO) {
        // 修改待选课程记录表
        Enrollment enrollment = enrollmentMapper.getEnrollmentById(endCourseDTO.getEnrollmentId());
        enrollment.setStatus(-1);
        enrollmentMapper.updateById(enrollment);
        // 修改学生选课记录表,将selectionInformation表中所有这个EnrollmentId为adminEndCourseDTO.getEnrollmentId()的数据的status改为2
        // 修改学生选课记录表
        // 创建条件构造器，指定需要修改的记录的条件
        UpdateWrapper<SelectionInformation> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("enrollment_id", endCourseDTO.getEnrollmentId())
                .set("status", 2);
        // 直接在条件构造器中设置要修改的字段和新值

        // 使用条件构造器执行更新操作
        selectionInformationMapper.update(null, updateWrapper);

        Course course = courseMapper.getCourseById(enrollment.getCourseId());
        Integer credit = course.getCredits();
        // 根据学生选课记录表中已修改的数据的student_id字段，增加students表中对应学生的学分

        // 通过该从待选课程中选了课的学生的ID列表
        List<Long> studentIds = selectionInformationMapper.getStudentsByEnrollmentId(endCourseDTO.getEnrollmentId());
        for (Long studentId : studentIds) {
            // 增加学生的学分
            Student student = studentMapper.selectById(studentId);
            if (student != null) {
                student.setLearnCredits(student.getLearnCredits() + credit);
                studentMapper.updateById(student);
            }
        }
    }

    /**
     * 老师查看自己课程中的学生信息
     * @param teacherGetStudentOnCourseListDTO
     * @return
     */
    @Override
    public StudentListVO getCourseStudentList(TeacherGetStudentOnCourseListDTO teacherGetStudentOnCourseListDTO) {
        List<StudentInfoVO>  studentInfoVOList = selectionInformationMapper.getStudentInfoByEnrollment(teacherGetStudentOnCourseListDTO.getEnrollmentId());
        return new StudentListVO(studentInfoVOList);
    }

    /**
     * 老师移除自己课程中的学生信息
     * @param removeStudentFromCourseDTO
     */
    @Override
    public void removeStudentFromCourse(RemoveStudentFromCourseDTO removeStudentFromCourseDTO) {
        SelectionInformation selectionInformation = selectionInformationMapper.getSelectionInformationById(removeStudentFromCourseDTO.getSelectInfoId());
        selectionInformation.setStatus(-1);
        selectionInformationMapper.updateById(selectionInformation);
        // 减少选课信息中的对应课程的人数
        Enrollment enrollment = enrollmentMapper.getEnrollmentById(selectionInformation.getEnrollmentId());
        enrollment.setPresentNum(enrollment.getPresentNum()-1);
    }

    @Override
    public void deleteCourseReview(TeacherDeleteCourseReviewDTO teacherDeleteCourseReviewDTO) {
        CourseReview courseReview = courseReviewMapper.selectById(teacherDeleteCourseReviewDTO.getReviewId());
        courseReview.setStatus(-1);
        courseReviewMapper.updateById(courseReview);
    }

    /**
     * 老师为自己的课程添加学生
     * @param teacherAddStudentToCourse
     */
    @Override
    public void teacherAddStudentToCourse(TeacherAddStudentToCourse teacherAddStudentToCourse) {
        // 获取进行选课的学生的信息
        Student student = studentMapper.getStudentByNumAndName(teacherAddStudentToCourse.getStudentNum(),teacherAddStudentToCourse.getStudentName());
        if (student == null){
            throw new CommonException("学生不存在或者信息错误，添加学生到课程失败");
        }
        // 获取待选课程信息
        Enrollment  enrollment = enrollmentMapper.getEnrollmentById(teacherAddStudentToCourse.getEnrollmentId());
        if (enrollment.getStatus() != 1){
            throw new CommonException("课程状态不正确，添加学生到课程失败");
        }
        // 进行验证，看是否容量超过了，以及学生年级是否符合要求
        if (enrollment.getMaxNum() <= enrollment.getPresentNum()){
            // 容量超过了,抛出异常
            throw new CommonException("容量不足，选课失败");
        }
        if (!Objects.equals(student.getGrade(), enrollment.getGrade())){
            // 年级不符合要求，抛出异常
            throw new CommonException("所在年级不符合要求，选课失败");
        }
        if (!(enrollment.getMinCredits()<=student.getLearnCredits() && student.getLearnCredits()<=enrollment.getMaxCredits())){
            // 学分不符合要求，抛出异常
            throw new CommonException("学分不符合要求，选课失败");
        }
        // 查看它所选的已有课程是否会与该课程产生冲突
        Integer total = selectionInformationMapper.getStudentCourseTotal(BaseContext.getCurrentUser().getUserId(),null,null);
        List<StudentCourseVO> studentCourseList = selectionInformationMapper.getStudentCourseList(0,total,BaseContext.getCurrentUser().getUserId(),null,null);
        Integer week = enrollment.getWeek();
        Integer onClass = enrollment.getOnClass();
        for (StudentCourseVO studentCourseVO : studentCourseList) {
            if (Objects.equals(studentCourseVO.getWeek(), week) && Objects.equals(studentCourseVO.getOnClass(), onClass)){
                // 冲突，抛出异常   TODO
                throw new CommonException("课程冲突，选课失败");
            }
        }
        // 进行选课
        enrollment.setPresentNum(enrollment.getPresentNum()+1);
        enrollmentMapper.updateById(enrollment);
        // 查找是否原先有选课记录
        SelectionInformation selectionInformation = selectionInformationMapper.getSelectionInformationByEnrollmentIdAndStudentId(student.getStudentId(),enrollment.getEnrollmentId());
        if (selectionInformation != null){
            // 有选课记录，修改选课记录的状态为正常即可，不用新增
            selectionInformation.setStatus(1);
            selectionInformationMapper.updateById(selectionInformation);
            return;
        }
        // 生成选课记录
        selectionInformation = new SelectionInformation();
        selectionInformation.setCourseId(enrollment.getCourseId());
        selectionInformation.setStudentId(student.getStudentId());
        selectionInformation.setEnrollmentId(enrollment.getEnrollmentId());
        selectionInformationMapper.insert(selectionInformation);
    }

    @Override
    public void updateSelectCourse(UpdateEnrollmentDTO updateEnrollmentDTO) {
        Enrollment e = enrollmentMapper.getEnrollmentById(updateEnrollmentDTO.getEnrollmentId());
        BeanUtils.copyProperties(updateEnrollmentDTO,e);
        enrollmentMapper.updateById(e);
    }
}
